#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
大语言模型分析器
使用Deepseek等大语言模型对金融新闻进行深度分析
"""

import os
import json
import yaml
import logging
import requests
from datetime import datetime
from pathlib import Path

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

class LLMAnalyzer:
    """大语言模型分析器，使用先进的大模型对新闻和市场数据进行深入分析"""
    
    def __init__(self, config_path='config/config.yaml'):
        """
        初始化大语言模型分析器
        
        Args:
            config_path: 配置文件路径
        """
        self.config_path = config_path
        self.config = self._load_config()
        self.llm_config = self.config.get('llm_analysis', {})
        self.model_name = self.llm_config.get('model', 'deepseek')
        self.api_key = self.llm_config.get('api_key', '')
        self.api_url = self.llm_config.get('api_url', '')
        
        logger.info(f"大语言模型分析器初始化完成，使用模型：{self.model_name}")
    
    def _load_config(self):
        """
        加载配置文件
        
        Returns:
            dict: 配置信息
        """
        try:
            with open(self.config_path, 'r', encoding='utf-8') as f:
                config = yaml.safe_load(f)
            logger.info(f"成功加载配置文件: {self.config_path}")
            return config
        except Exception as e:
            logger.error(f"加载配置文件失败: {e}")
            return {}
    
    def analyze_news(self, news_list):
        """
        使用大语言模型分析新闻列表
        
        Args:
            news_list: 新闻列表，每条新闻包含标题、内容等字段
            
        Returns:
            dict: 分析结果，包含市场洞察、行业趋势等
        """
        try:
            if not news_list:
                logger.warning("没有新闻数据用于分析")
                return {}
            
            # 提取新闻的核心内容
            news_texts = []
            for news in news_list:
                news_texts.append(f"标题: {news.get('title', '')}\n内容: {news.get('content', '')[:500]}...")
            
            # 构建提示词
            prompt = self._build_analysis_prompt(news_texts)
            
            # 调用大语言模型API
            result = self._call_llm_api(prompt)
            
            # 解析API返回的结果
            insights = self._parse_llm_response(result)
            
            logger.info(f"大语言模型分析完成，生成 {len(insights.get('insights', []))} 条洞察")
            return insights
            
        except Exception as e:
            logger.error(f"大语言模型分析失败: {e}")
            return {
                "insights": [],
                "market_summary": "大语言模型分析过程中发生错误",
                "industry_trends": {},
                "risk_factors": []
            }
    
    def analyze_stocks(self, stock_data, news_analysis):
        """
        分析股票数据并结合新闻分析结果
        
        Args:
            stock_data: 股票数据，包含股票代码、价格等信息
            news_analysis: 新闻分析结果
            
        Returns:
            dict: 深度分析结果
        """
        try:
            if not stock_data:
                logger.warning("没有股票数据用于分析")
                return {}
            
            # 构建提示词
            prompt = self._build_stock_analysis_prompt(stock_data, news_analysis)
            
            # 调用大语言模型API
            result = self._call_llm_api(prompt)
            
            # 解析API返回的结果
            analysis = self._parse_llm_response(result)
            
            logger.info("大语言模型股票深度分析完成")
            return analysis
            
        except Exception as e:
            logger.error(f"大语言模型股票分析失败: {e}")
            return {
                "insights": [],
                "stock_recommendations": [],
                "investment_strategies": []
            }
    
    def generate_market_commentary(self, analysis_results, strategy_report):
        """
        生成市场评论和深度洞察
        
        Args:
            analysis_results: 分析结果数据
            strategy_report: 策略报告数据
            
        Returns:
            dict: 市场评论和洞察
        """
        try:
            # 构建提示词
            prompt = self._build_commentary_prompt(analysis_results, strategy_report)
            
            # 调用大语言模型API
            result = self._call_llm_api(prompt)
            
            # 解析API返回的结果
            commentary = self._parse_llm_response(result)
            
            logger.info("大语言模型市场评论生成完成")
            return commentary
            
        except Exception as e:
            logger.error(f"大语言模型生成市场评论失败: {e}")
            return {
                "market_commentary": "无法生成市场评论",
                "investment_thesis": [],
                "long_term_outlook": "数据不足，无法提供长期展望"
            }
    
    def _build_analysis_prompt(self, news_texts):
        """
        构建新闻分析提示词
        
        Args:
            news_texts: 新闻文本列表
            
        Returns:
            str: 提示词
        """
        news_content = "\n\n".join(news_texts[:10])  # 限制处理的新闻数量
        
        prompt = f"""作为金融分析专家，请分析以下财经新闻，提取关键洞察并分析可能对股市的影响:

{news_content}

请提供以下分析:
1. 市场总体趋势分析：基于新闻内容，分析市场可能的走向和关键驱动因素
2. 行业影响分析：识别新闻中提到的行业，分析每个行业可能面临的机遇和挑战
3. 投资洞察：提出3-5条基于新闻的投资洞察，包括可能的投资机会和风险
4. 风险因素：识别可能影响市场的主要风险因素
5. 市场情绪评估：分析新闻整体传递的市场情绪（积极、中性或消极）

请以JSON格式返回结果，包含以下字段:
1. market_summary: 市场总结
2. industry_trends: 行业趋势，每个行业包含outlook（展望）和reasons（原因）
3. insights: 投资洞察列表
4. risk_factors: 风险因素列表
5. market_sentiment: 市场情绪评分（0-1，0表示极度消极，1表示极度积极）
"""
        return prompt
    
    def _build_stock_analysis_prompt(self, stock_data, news_analysis):
        """
        构建股票分析提示词
        
        Args:
            stock_data: 股票数据
            news_analysis: 新闻分析结果
            
        Returns:
            str: 提示词
        """
        # 转换股票数据为易读格式
        stock_info = []
        for code, data in list(stock_data.items())[:10]:  # 限制处理的股票数量
            stock_info.append(
                f"股票代码: {code}, 名称: {data.get('name', '')}, "
                f"行业: {data.get('industry', '')}, 预测: {data.get('prediction', '')}, "
                f"置信度: {data.get('confidence', 0)}, 情感得分: {data.get('sentiment_score', 0)}"
            )
        
        stock_content = "\n".join(stock_info)
        
        market_summary = news_analysis.get('market_summary', '无市场总结')
        
        prompt = f"""作为金融投资顾问，请基于以下股票数据和市场分析，提供深度投资洞察:

股票数据:
{stock_content}

市场分析摘要:
{market_summary}

请提供以下内容:
1. 每只股票的深度分析，包括基本面评估、技术面评估和可能的投资价值
2. 投资组合建议，包括配置比例和持有期限
3. 针对不同风险偏好的投资策略
4. 潜在的套利或对冲机会
5. 中长期投资主题和布局建议

请以JSON格式返回结果，包含以下字段:
1. stock_analysis: 股票分析结果，每只股票包含analysis（分析）和rating（评级：强买、买入、持有、卖出、强卖）
2. portfolio_recommendations: 投资组合建议，包括股票代码、配置比例和持有期限
3. strategies: 不同风险偏好的投资策略
4. themes: 中长期投资主题
"""
        return prompt
    
    def _build_commentary_prompt(self, analysis_results, strategy_report):
        """
        构建市场评论提示词
        
        Args:
            analysis_results: 分析结果
            strategy_report: 策略报告
            
        Returns:
            str: 提示词
        """
        # 提取策略报告中的市场概述
        market_overview = strategy_report.get('market_overview', '无市场概述')
        
        # 提取主要推荐
        recommendations = []
        for rec in strategy_report.get('recommendations', [])[:5]:
            recommendations.append(
                f"{rec.get('stock_name', '')}({rec.get('stock_code', '')}): "
                f"{rec.get('action', '')}, 理由: {rec.get('reason', '')}"
            )
        
        recommendations_text = "\n".join(recommendations)
        
        prompt = f"""作为资深市场分析师，请基于以下市场概述和投资建议，撰写一份详尽的市场评论:

市场概述:
{market_overview}

主要投资建议:
{recommendations_text}

请提供以下内容:
1. 深度市场评论：分析市场当前状态、主要驱动因素和可能的发展趋势
2. 宏观经济因素分析：讨论宏观经济因素如何影响当前市场
3. 行业轮动分析：识别行业轮动趋势和背后的逻辑
4. 投资主题分析：提出3-5个有潜力的投资主题及其理由
5. 关键指标监控：建议投资者应关注哪些关键指标来把握市场动向

请以清晰、专业的语言撰写，避免过于技术性的术语，使普通投资者也能理解。

请以JSON格式返回结果，包含以下字段:
1. market_commentary: 市场评论
2. economic_factors: 宏观经济因素分析
3. sector_rotation: 行业轮动分析
4. investment_themes: 投资主题分析，每个主题包含theme（主题名称）和rationale（理由）
5. key_indicators: 关键指标监控列表
"""
        return prompt
    
    def _call_llm_api(self, prompt):
        """
        调用大语言模型API
        
        Args:
            prompt: 提示词
            
        Returns:
            str: API返回的结果
        """
        if self.llm_config.get('simulation_mode', True):
            # 模拟模式，返回预定义的结果
            logger.info("使用模拟模式，不调用实际API")
            return self._get_simulated_response(prompt)
        
        try:
            if self.model_name.lower() == 'deepseek':
                return self._call_deepseek_api(prompt)
            else:
                logger.warning(f"不支持的模型: {self.model_name}，使用模拟数据")
                return self._get_simulated_response(prompt)
                
        except Exception as e:
            logger.error(f"调用LLM API失败: {e}")
            return "{}"
    
    def _call_deepseek_api(self, prompt):
        """
        调用Deepseek API
        
        Args:
            prompt: 提示词
            
        Returns:
            str: API返回的结果
        """
        # 实际项目中应该填入真实的API调用代码
        # 以下是一个示例
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.api_key}"
        }
        
        data = {
            "model": "deepseek-chat",
            "messages": [
                {"role": "user", "content": prompt}
            ],
            "temperature": 0.3,
            "max_tokens": 2000
        }
        
        logger.info("调用Deepseek API")
        response = requests.post(self.api_url, headers=headers, json=data)
        
        if response.status_code == 200:
            result = response.json()
            return result.get('choices', [{}])[0].get('message', {}).get('content', '{}')
        else:
            logger.error(f"Deepseek API调用失败, 状态码: {response.status_code}, 响应: {response.text}")
            return "{}"
    
    def _get_simulated_response(self, prompt):
        """
        获取模拟的API响应
        
        Args:
            prompt: 提示词
            
        Returns:
            str: 模拟的响应
        """
        # 根据提示词内容判断需要返回的模拟数据类型
        if "分析以下财经新闻" in prompt:
            return self._get_simulated_news_analysis()
        elif "基于以下股票数据" in prompt:
            return self._get_simulated_stock_analysis()
        elif "撰写一份详尽的市场评论" in prompt:
            return self._get_simulated_market_commentary()
        else:
            return "{}"
    
    def _get_simulated_news_analysis(self):
        """
        获取模拟的新闻分析结果
        
        Returns:
            str: 模拟的新闻分析JSON字符串
        """
        return json.dumps({
            "market_summary": "市场表现出强劲的结构性特征，科技和新能源板块受益于政策支持和行业趋势，表现突出。医药板块受到政策调整影响，存在波动。金融科技推动银行业转型，有望改善整体业绩。消费复苏趋势明显，零售和餐饮行业受益。整体市场趋势偏向积极，预计将继续上行。",
            "industry_trends": {
                "科技/半导体": {
                    "outlook": "非常积极",
                    "reasons": "AI芯片需求爆发，产业政策支持，核心技术突破加速"
                },
                "新能源": {
                    "outlook": "积极",
                    "reasons": "政策支持力度加大，产销量持续增长，全球市场份额提升"
                },
                "医药": {
                    "outlook": "中性偏谨慎",
                    "reasons": "创新药研发进展良好，但政策调整带来的不确定性增加"
                },
                "银行": {
                    "outlook": "中性偏积极",
                    "reasons": "金融科技转型显现成效，资产质量改善，但宏观因素影响较大"
                },
                "消费/零售": {
                    "outlook": "积极",
                    "reasons": "消费复苏明显，线下流量恢复，线上线下融合加速"
                }
            },
            "insights": [
                "AI芯片产业链或将迎来持续高景气期，建议关注具有自主研发能力的龙头企业",
                "新能源汽车产业链受政策利好刺激，动力电池材料企业值得重点关注",
                "消费复苏进程加速，高端消费和餐饮行业将率先受益",
                "医药创新是长期主线，但短期内需谨慎对待政策变动带来的波动",
                "银行业数字化转型是提升估值的关键，关注转型领先的大型银行"
            ],
            "risk_factors": [
                "全球地缘政治冲突可能影响市场风险偏好",
                "通胀压力可能导致货币政策收紧",
                "行业政策调整可能导致相关板块大幅波动",
                "经济复苏不及预期可能影响消费信心",
                "产能过剩风险在部分新兴行业显现"
            ],
            "market_sentiment": 0.72
        }, ensure_ascii=False)
    
    def _get_simulated_stock_analysis(self):
        """
        获取模拟的股票分析结果
        
        Returns:
            str: 模拟的股票分析JSON字符串
        """
        return json.dumps({
            "stock_analysis": {
                "688981": {
                    "analysis": "中芯国际作为中国领先的晶圆代工企业，受益于全球半导体国产化趋势和AI芯片需求爆发。公司产能持续扩张，技术水平不断提升，有望赶超国际竞争对手。短期内资本开支较大，但长期成长空间广阔。",
                    "rating": "强买入"
                },
                "300750": {
                    "analysis": "宁德时代在动力电池领域拥有全球领先的市场份额，产品技术先进，客户基础稳固。随着新能源汽车渗透率提升，公司业绩有望保持高增长。关注原材料价格波动和国际竞争加剧的风险。",
                    "rating": "买入"
                },
                "600100": {
                    "analysis": "同方股份在数字化转型和AI技术应用方面布局较早，正积极转型。公司在多元化战略推进中取得进展，AI业务增长迅速。但非核心业务对利润贡献有待观察，建议关注转型进展。",
                    "rating": "买入"
                },
                "300347": {
                    "analysis": "泰格医药面临行业竞争加剧和成本上升的挑战，短期业绩承压。海外业务扩张不及预期，国内业务增速放缓。建议等待估值调整到位后再考虑布局。",
                    "rating": "卖出"
                },
                "603883": {
                    "analysis": "海底捞作为餐饮行业龙头，直接受益于消费复苏。公司数字化运营能力强，新门店扩张节奏稳健，品牌效应显著。毛利率改善趋势明显，现金流状况良好。",
                    "rating": "买入"
                }
            },
            "portfolio_recommendations": [
                {"stock_code": "688981", "proportion": "25%", "holding_period": "6-12个月"},
                {"stock_code": "300750", "proportion": "20%", "holding_period": "6-12个月"},
                {"stock_code": "600100", "proportion": "15%", "holding_period": "3-6个月"},
                {"stock_code": "603883", "proportion": "15%", "holding_period": "3-6个月"},
                {"stock_code": "002594", "proportion": "15%", "holding_period": "6-12个月"},
                {"stock_code": "601398", "proportion": "10%", "holding_period": "3-6个月"}
            ],
            "strategies": {
                "激进型": "重点配置科技和新能源板块，关注AI和新能源汽车主题，适当参与高弹性个股",
                "稳健型": "均衡配置科技、新能源和消费板块，主要选择行业龙头企业，适当配置银行股提高组合稳定性",
                "保守型": "以大型蓝筹股为主，关注银行、消费等防御性板块，回避高估值和高波动性行业"
            },
            "themes": [
                "AI芯片和大模型：人工智能应用加速渗透各行业，计算力需求爆发",
                "新能源汽车产业链：政策支持下，渗透率持续提升，龙头企业竞争优势扩大",
                "消费复苏：后疫情时代，消费需求释放，高端消费和服务业率先受益",
                "金融科技：传统金融机构数字化转型，提升效率和风控能力",
                "医药创新：创新药研发进入收获期，具备自主研发能力的企业价值凸显"
            ]
        }, ensure_ascii=False)
    
    def _get_simulated_market_commentary(self):
        """
        获取模拟的市场评论
        
        Returns:
            str: 模拟的市场评论JSON字符串
        """
        return json.dumps({
            "market_commentary": "当前市场呈现明显的结构性特征，科技、新能源及消费等板块表现强势，引领市场走向。A股正处于估值修复和业绩驱动的上行通道中，但结构分化明显。政策面持续释放积极信号，流动性环境整体宽松，为市场提供了良好的外部条件。投资者应当重点关注科技创新、消费升级和绿色转型等主题，把握结构性机会。同时，需警惕全球流动性收紧、地缘政治风险等外部因素可能带来的波动。",
            
            "economic_factors": "宏观经济稳中向好，经济增长动能持续恢复。消费数据显示内需回暖，社会消费品零售总额同比增长超预期。工业生产稳步增长，高技术制造业和战略性新兴产业保持较高增速。货币政策延续稳健基调，财政政策更加积极有为，政策协同效应明显。通胀压力整体可控，PPI与CPI剪刀差收窄，企业盈利能力有望提升。全球经济复苏不均衡，发达经济体增长动能减弱，新兴市场表现相对强劲。",
            
            "sector_rotation": "市场正处于从传统周期板块向成长板块轮动的过程中。科技创新板块受益于政策支持和产业升级，表现强势。新能源产业链在政策利好和产业发展双重驱动下，延续强劲势头。消费板块随着复苏进程加快，估值逐步修复。医药板块因政策调整而波动，但创新药细分领域表现分化。金融板块特别是银行估值处于历史低位，具备防御价值。未来1-2个季度，科技、新能源和消费有望继续引领市场，传统周期性行业可能面临估值压力。",
            
            "investment_themes": [
                {
                    "theme": "AI计算基础设施",
                    "rationale": "大模型应用场景爆发，对算力需求持续增长，芯片、服务器、数据中心等基础设施投入加大，产业链公司业绩有望超预期增长。"
                },
                {
                    "theme": "新能源汽车全产业链",
                    "rationale": "政策支持力度加大，技术进步推动成本下降，渗透率快速提升，产业链上下游企业有望迎来量价齐升。"
                },
                {
                    "theme": "消费升级与服务业复苏",
                    "rationale": "居民收入稳步增长，消费信心恢复，高端消费品和服务消费需求释放，相关企业业绩弹性显著。"
                },
                {
                    "theme": "国产替代与科技自主",
                    "rationale": "全球供应链重构背景下，国产替代进程加速，核心技术领域的自主创新企业价值凸显。"
                },
                {
                    "theme": "数字经济与产业数字化",
                    "rationale": "传统行业数字化转型加速，企业数字化投入增加，数字技术服务提供商迎来广阔市场空间。"
                }
            ],
            
            "key_indicators": [
                "流动性指标：关注货币供应量M2增速和社会融资规模增长情况",
                "行业景气度：跟踪PMI、工业增加值等反映实体经济活力的指标",
                "消费恢复程度：监测社会消费品零售总额、服务消费占比等数据",
                "企业盈利：关注上市公司业绩增速和盈利能力变化",
                "市场情绪：观察北向资金流向、融资融券余额变动、市场交投活跃度",
                "估值水平：对比市场整体P/E与历史分位，行业估值相对差异"
            ]
        }, ensure_ascii=False)
    
    def _parse_llm_response(self, response):
        """
        解析LLM API的响应
        
        Args:
            response: API响应
            
        Returns:
            dict: 解析后的结果
        """
        try:
            # 尝试解析JSON
            result = json.loads(response)
            return result
        except Exception as e:
            logger.error(f"解析LLM响应失败: {e}")
            # 如果解析失败，返回最小化的结果结构
            return {
                "error": "解析响应失败",
                "raw_response": response[:100] + "..." if len(response) > 100 else response
            } 